import type { AxiosInstance, InternalAxiosRequestConfig } from 'axios';
import axios from 'axios';

import type { ApiError, ApiResponse } from './types';
import { useAuthStore } from '@/stores/auth';

const SUCCESS_CODE = 0;

/**
 * 自定义 HTTP 客户端接口
 * 响应拦截器会将 AxiosResponse<ApiResponse<T>> 转换为 ApiResponse<T>
 */
interface HttpClient extends Omit<AxiosInstance, 'get' | 'post' | 'put' | 'delete' | 'patch'> {
  get: <T = any>(url: string, config?: any) => Promise<ApiResponse<T>>;
  post: <T = any>(url: string, data?: any, config?: any) => Promise<ApiResponse<T>>;
  put: <T = any>(url: string, data?: any, config?: any) => Promise<ApiResponse<T>>;
  delete: <T = any>(url: string, config?: any) => Promise<ApiResponse<T>>;
  patch: <T = any>(url: string, data?: any, config?: any) => Promise<ApiResponse<T>>;
}

/**
 * 创建axios实例
 */
const http = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 40000,
}) as HttpClient;

/**
 * 请求拦截器：添加token
 */
http.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 从 auth store 获取 token
    const authStore = useAuthStore();
    const token = authStore.token;
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  error => {
    return Promise.reject(error);
  },
);

/**
 * 响应拦截器：处理统一数据格式
 */
http.interceptors.response.use(
  response => {
    // 验证响应code，成功时返回data
    if (response.data.code === SUCCESS_CODE) {
      return Promise.resolve(response.data);
    }

    if (response.data.code === 401) {
      const authStore = useAuthStore();
      authStore.clearAuth();
    }

    // code不符合预期，抛出错误
    const error: ApiError = Object.assign(
      new Error(response.data.message || '请求失败'),
      {
        code: String(response.data.code || ''),
        response,
      },
    );
    return Promise.reject(error);
  },
  error => {
    // 处理HTTP错误
    const message = error.response?.data?.message || error.message || '请求失败';
    console.error('请求错误:', message);
    return Promise.reject(error);
  },
);

export { http };
